package utils.database;

import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.Lock;

import org.apache.commons.lang3.StringEscapeUtils;

import utils.timer.Timer;

public class DBStream extends Thread {
	
	private static int numToSendToDB = 5000;
	private static int countQuery;
	private static int queryProcessed = 0;
	private static StringBuffer queryList = new StringBuffer();
	
	private static StringBuffer queryElement = new StringBuffer();
	private static StringBuffer queryAttribute = new StringBuffer();
	private static StringBuffer queryPaths = new StringBuffer();
	private static boolean read = true;
	
	private static List<Thread> listThreads = new ArrayList<Thread>();
	
	private DBStream()	{	}
	
	/*public static void addQuery(String query)
	{
		countQuery++;
		
		queryList.append(query.substring(0,query.length()));
	}*/
	
	public static void addAttribute(String valueQuery)
	{
		if(queryAttribute.length() == 0)
		{
			queryAttribute.append("INSERT INTO \"Attributes\" (document_id, parent_dewey, name, value) VALUES ");
			queryAttribute.append(valueQuery);
		}
		else
		{
			queryAttribute.append("," + valueQuery);
		}		
		countQuery++;
	}
	
	public static void addElement(String valueQuery)
	{
		if(queryElement.length() == 0)
		{
			queryElement.append("INSERT INTO \"Elements\" (document_id, dewey, path_id, value) VALUES ");
			queryElement.append(valueQuery);
		}
		else
		{
			queryElement.append("," + valueQuery);
		}		
		countQuery++;
	}
	
	public static void addPaths(String valueQuery)
	{
		if(queryPaths.length() == 0)
		{
			queryPaths.append("INSERT INTO \"Paths\" (document_id, path_id, path) VALUES ");
			queryPaths.append(valueQuery);
		}
		else
		{
			queryPaths.append("," + valueQuery);
		}		
		countQuery++;
	}
	
	public static void flush()	
	{		
		queryProcessed += countQuery;
		countQuery = 0;
		
		if(listThreads.size() == 1)
		{
			try {
				listThreads.get(0).join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			/*
			for(Thread item : listThreads)
			{
				try {
					if(item.isAlive())
						item.join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}*/
		}
		DBStream db = new DBStream();
		listThreads.add(db);
		db.run();
		//db.start();
		System.out.println("Query's processed: " + queryProcessed);
	}
	
	@Override
	public void run() {		
		super.run();		
		try 
		{
			StringBuilder queryListLocal = new StringBuilder();
			queryListLocal.append("begin;");
			
			if(queryElement.length() > 0) 				
				queryListLocal.append(queryElement.toString() + ";");
			
			if(queryAttribute.length() > 0)
				queryListLocal.append(queryAttribute.toString() + ";");
			
			if(queryPaths.length() > 0)
				queryListLocal.append(queryPaths.toString() + ";");
			
			queryListLocal.append("commit;");
			
			queryAttribute = new StringBuffer();
			queryElement = new StringBuffer();
			queryPaths = new StringBuffer();
			
			System.gc();
			
			/*while(!DBStream.read)
			{			
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}*/
			//DBStream.read = false;
			//if(countQuery < 800000) return;
			Statement query = DB.getConnection().createStatement();			
			query.executeUpdate(queryListLocal.toString());			
			queryList = new StringBuffer();
			//DBStream.read = true;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			System.out.println(queryList.toString());
			System.out.println( "\n");
		}
	}
	
	public static boolean canFlush()
	{
		if(countQuery > getNumToSendToDB())
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	public static int getCountQuery() {
		return countQuery;
	}

	public static void setNumToSendToDB(int numToSendToDB) {
		DBStream.numToSendToDB = numToSendToDB;
	}

	public static int getNumToSendToDB() {
		return numToSendToDB;
	}
	
	public static String cleanup(String value)
	{
		value = value.replaceAll("'", "''");
		
		return StringEscapeUtils.escapeJava(value);
	}
	
	public static void ClearBD() throws SQLException
	{		
		Timer t = new Timer();
		Statement s = DB.getConnection().createStatement();
		s.addBatch("TRUNCATE TABLE \"Elements\"");
		s.addBatch("TRUNCATE TABLE \"Paths\"");
		s.addBatch("TRUNCATE TABLE \"Attributes\"");
		t.start();
		s.executeBatch();
		t.stop();
		
		System.out.println("Database cleaned in " + t.timeElapsed() + " ms");
	}
}

